#if !defined(_CAANIMATE_OBJECT_H_)
#define _CAANIMATE_OBJECT_H_

#include "AObject.h"
#include "ASpriteModel.h"

class CAICoordinateConverter
{
public:
	virtual void game2pixel(CCPoint& pos, bool bFollowCamera) const = 0;
	virtual void pixel2game(CCPoint& pos, bool bFollowCamera) const = 0;
};

class CAAnimateObject
{
private:

protected:
	bool	_bFollowCamera;

	ccTime _timeBegin;
	CAFixArray<CASpriteModelPoseModifierKey> _keys;
	float _duration;
	EAnimationMode _mode;
	//Animation ==> lerpKey
	//Game code ==> gameKey
	//lerpKey + gameKey + parent.combinedKey ==> combinedKey
	//combinedKey ==> render state
	CASpriteModelPoseModifierKey _gameKey;

	int _updated;
	CASpriteModelPoseModifierKey _combinedKeyLast;
	CASpriteModelPoseModifierKey _combinedKey;
	
	CCRect	_actionBoundingBox;
	bool _bAnimationDone;

	virtual void _onAnimationStart() {};
	virtual void _onAnimationStop() {};

	virtual CCSpriteFrame* _onAnimateUpdateFrame(ccTime timeNow) { return null; };
	virtual void _onAnimateUpdate(ccTime timeNow) {};
public:
	CAAnimateObject(void);
	virtual ~CAAnimateObject(void);

	inline void setFollowCamera(bool b)
	{
		_bFollowCamera = b;
	}

	//these functions can modifiy _gameKey
	virtual void setPos(const CCPoint& pos)
	{
		setPos(pos.x, pos.y);
	}
    virtual void setPosX(float x)
	{
		_Assert(x > -999999999.0f && x < 999999999.0f);
		_gameKey.x = x;
		_gameKey.ModifierOr(PM_POS);
	}
    virtual void setPosY(float y)
	{
		_Assert(y > -999999999.0f && y < 999999999.0f);
		_gameKey.y = y;
		_gameKey.ModifierOr(PM_POS);
	}
    virtual void setPos(float x, float y)
	{
		_Assert(x > -999999999.0f && x < 999999999.0f);
		_Assert(y > -999999999.0f && y < 999999999.0f);
		_gameKey.x = x;
		_gameKey.y = y;
		_gameKey.ModifierOr(PM_POS);
	}
	virtual void setRot(float fRotation)
	{
		_gameKey.rot = fRotation;
		_gameKey.ModifierOr(PM_ROT);
	}
	virtual void setSclX(float fScaleX)
	{
		_gameKey.scalex = fScaleX;
		_gameKey.ModifierOr(PM_SCALE);
	}
	virtual void setSclY(float fScaleY)
	{
		_gameKey.scaley = fScaleY;
		_gameKey.ModifierOr(PM_SCALE);
	}
	virtual void setScl(float fScale)
	{
		_gameKey.scalex = fScale;
		_gameKey.scaley = fScale;
		_gameKey.ModifierOr(PM_SCALE);
	}
	virtual void setAnchorPos(const CCPoint& anchor)
	{
		_gameKey.ax = anchor.x;
		_gameKey.ay = anchor.y;
		_gameKey.ModifierOr(PM_APOS);
	}
	virtual void setAlpha(float alpha)
	{
		_gameKey.alpha = alpha;
		_gameKey.ModifierOr(PM_ALPHA);
	}

	//getters
	const CASpriteModelPoseModifierKey& getGameKey() const { return _gameKey; }
	const CASpriteModelPoseModifierKey& getCombinedKey() const { return _combinedKey; }
	int getUpdateCounter() const { return _updated; }
	const CASpriteModelPoseModifierKey& getCombinedKeyLast() const { return _combinedKeyLast; }

    virtual CCPoint getPos(void) const
	{
		return ccp(_combinedKey.x, _combinedKey.y);
	}
    virtual void getPos(float* x, float* y)  const
	{
		_Assert(x && y);
		*x = _combinedKey.x;
		*y = _combinedKey.y;
	}
    virtual float getPosX(void) const
	{
		return _combinedKey.x;
	}
    virtual float getPosY(void) const
	{
		return _combinedKey.y;
	}
	
	virtual float getRot(void) const
	{
		return _combinedKey.rot;
	}
	virtual float getSclX(void) const
	{
		return _combinedKey.scalex;
	}
	virtual float getSclY(void) const
	{
		return _combinedKey.scaley;
	}
	virtual float getScl(void) const
	{
		_Assert(_combinedKey.scalex == _combinedKey.scaley);
		return _combinedKey.scalex;
	}
	virtual float getAlpha(void) const
	{
		return _combinedKey.alpha;
	}

	float getAnimationPercent(ccTime timeNow) const
	{
		return (timeNow - _timeBegin) / _duration;
	}
	bool isAnimationDone() const
	{
		return _bAnimationDone;
	}
	void setActionBoundingBox(const CCRect& rect)
	{
		_actionBoundingBox = rect;
	}


	void startAnimation(ccTime timeNow, CASpriteModelPoseModifierKey* pkeys, size_t count, EAnimationMode mode, float dutation);
	void updateAnimation(CAICoordinateConverter* pstage, ccTime timeNow);
};

#endif //_CAANIMATE_OBJECT_H_
